]> dgit.raspbian.org Git - gnome-shell.git/commitdiff
gdm: Limit verification cancellations to be conform to allowed-failures
authorMarco Trevisan (Treviño) <mail@3v1n0.net>
Mon, 1 Feb 2021 12:10:45 +0000 (13:10 +0100)
committerMarge Bot <marge-bot@gnome.org>
Fri, 12 Feb 2021 20:26:00 +0000 (20:26 +0000)
As per previous commit the user can cancel an ongoing authentication via
Escape key and that will always send the user back to the clock view in
lockscreen or user-selection view in login prompt.

However, we can be a little more permissive and don't switch view to be
able to restart the authentication without further action.

To avoid this to be abused though, we consider the user verification
cancellation via escape key to be a "soft-failure", so once the
configured "allowed-failures" gsettings value has been reached, we'd
just act as before, ignoring any further request (until we don't get
back to the user auth view).

In this way we still make brute-force attacks harder to do, while still
giving the well-behaving user some ability to fix mistakes.

Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/1622>

js/gdm/authPrompt.js
js/gdm/loginDialog.js
js/gdm/util.js

index dcc1d3f2893d53a23b94c7862aeb11a49de16054..feab52e89244abcb7f7185b761f3c123f594d6d5 100644 (file)
@@ -30,11 +30,13 @@ var AuthPromptStatus = {
     VERIFICATION_FAILED: 2,
     VERIFICATION_SUCCEEDED: 3,
     VERIFICATION_CANCELLED: 4,
+    VERIFICATION_IN_PROGRESS: 5,
 };
 
 var BeginRequestType = {
     PROVIDE_USERNAME: 0,
     DONT_PROVIDE_USERNAME: 1,
+    REUSE_USERNAME: 2,
 };
 
 var AuthPrompt = GObject.registerClass({
@@ -59,6 +61,7 @@ var AuthPrompt = GObject.registerClass({
         this._gdmClient = gdmClient;
         this._mode = mode;
         this._defaultButtonWellActor = null;
+        this._cancelledRetries = 0;
 
         let reauthenticationOnly;
         if (this._mode == AuthPromptMode.UNLOCK_ONLY)
@@ -196,6 +199,7 @@ var AuthPrompt = GObject.registerClass({
     }
 
     _activateNext(shouldSpin) {
+        this.verificationStatus = AuthPromptStatus.VERIFICATION_IN_PROGRESS;
         this.updateSensitivity(false);
 
         if (shouldSpin)
@@ -501,6 +505,9 @@ var AuthPrompt = GObject.registerClass({
             // We don't need to know the username if the user preempted the login screen
             // with a smartcard or with preauthenticated oVirt credentials
             beginRequestType = BeginRequestType.DONT_PROVIDE_USERNAME;
+        } else if (oldStatus === AuthPromptStatus.VERIFICATION_IN_PROGRESS) {
+            // We're going back to retry with current user
+            beginRequestType = BeginRequestType.REUSE_USERNAME;
         } else {
             // In all other cases, we should get the username up front.
             beginRequestType = BeginRequestType.PROVIDE_USERNAME;
@@ -549,7 +556,14 @@ var AuthPrompt = GObject.registerClass({
         if (this.verificationStatus == AuthPromptStatus.VERIFICATION_SUCCEEDED)
             return;
 
-        this.verificationStatus = AuthPromptStatus.VERIFICATION_CANCELLED;
+        if (this.verificationStatus === AuthPromptStatus.VERIFICATION_IN_PROGRESS) {
+            this._cancelledRetries++;
+            if (this._cancelledRetries > this._userVerifier.allowedFailures)
+                this.verificationStatus = AuthPromptStatus.VERIFICATION_FAILED;
+        } else {
+            this.verificationStatus = AuthPromptStatus.VERIFICATION_CANCELLED;
+        }
+
         this.reset();
     }
 });
index ad84c3e3c33a88d7f752a7deb08116788f1b46b9..6f66a275924481960668921afc78f4e1d58ca50c 100644 (file)
@@ -855,6 +855,7 @@ var LoginDialog = GObject.registerClass({
         this._resetGreeterProxy();
         this._sessionMenuButton.updateSensitivity(true);
 
+        const previousUser = this._user;
         this._user = null;
 
         if (this._nextSignalId) {
@@ -862,7 +863,11 @@ var LoginDialog = GObject.registerClass({
             this._nextSignalId = 0;
         }
 
-        if (beginRequest == AuthPrompt.BeginRequestType.PROVIDE_USERNAME) {
+        if (previousUser && beginRequest === AuthPrompt.BeginRequestType.REUSE_USERNAME) {
+            this._user = previousUser;
+            this._authPrompt.setUser(this._user);
+            this._authPrompt.begin({ userName: previousUser.get_user_name() });
+        } else if (beginRequest === AuthPrompt.BeginRequestType.PROVIDE_USERNAME) {
             if (!this._disableUserList)
                 this._showUserList();
             else
index 47bb2314e8c7af6d77cab9e372fdbd43ee9ec39e..54cd3463113313d45dea97276bd83fa8fcf417bc 100644 (file)
@@ -192,6 +192,10 @@ var ShellUserVerifier = class {
         }
     }
 
+    get allowedFailures() {
+        return this._settings.get_int(ALLOWED_FAILURES_KEY);
+    }
+
     begin(userName, hold) {
         this._cancellable = new Gio.Cancellable();
         this._hold = hold;